<?php

namespace app\common\model\banxi\learn;

use app\common\enums\AccountTypeEnum;
use app\common\enums\CoreCourseTypeEnum;
use app\common\enums\CourseDeliveryTypeEnum;
use app\common\enums\CourseFullTypeEnum;
use app\common\enums\LearnValidStatusEnum;
use app\common\enums\SubjectQuestionStatusEnum;
use app\common\enums\TrainerSalaryProjectEnum;
use app\common\model\banxi\core\CoreAccountClassHour;
use app\common\model\banxi\core\CoreCourseAppointment;
use app\common\model\banxi\core\CoreTrainerMonthSalaryDetail;
use app\common\model\banxi\course\Course;
use app\common\model\banxi\organization\Organization;
use app\common\model\banxi\student\Student;
use app\common\model\banxi\subject\SubjectQuestion;
use app\common\model\banxi\subject\SubjectTeach;
use app\common\model\banxi\trainer\Trainer;
use app\common\model\banxi\word\WordDictionary;
use app\common\model\common\BaseModel;
use app\common\service\trainer\TrainerSalaryService;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\ValidateException;
use think\model\concern\SoftDelete;

/**
 * 上课记录
 */
class LearnSkRecord extends BaseModel
{
    use SoftDelete;

    protected $name = 'banxi_learn_sk_record';

    protected $autoWriteTimestamp = true;

    protected $deleteTime = 'del';

    protected $defaultSoftDelete = 0;

    protected $append = [
        'learnValidStatusCn',
        'courseTypeCn',
        'courseFullTypeCn',
        'courseDeliveryTypeCn',
        'actualCourseIdList',
        'actualCourseList'
    ];

    protected $type = [
        'id' => 'string',
        'del' => 'string',
        'appointmentId' => 'string',
        'studentId' => 'string',
        'trainerId' => 'string',
        'courseId' => 'string',
        'isEnd' => 'boolean',
        'isCreateAntiForgetting' => 'boolean',
        'createTime' => 'timestamp:Y-m-d H:i:s',
        'updateTime' => 'timestamp:Y-m-d H:i:s',
    ];

    //-----------------------------------------------------------------------------------
    //｜                                   获取器                                       ｜
    //-----------------------------------------------------------------------------------

    public function getLearnValidStatusCnAttr($value, $data)
    {
        $value = $value ?: ($data['learnValidStatus'] ?? '');
        return (new LearnValidStatusEnum())->getDescription($value) ?? '';
    }

    public function getCourseTypeCnAttr($value, $data)
    {
        $value = $value ?: ($data['courseType'] ?? '');
        return (new CoreCourseTypeEnum())->getDescription($value) ?? '';

    }

    public function getCourseFullTypeCnAttr($value, $data)
    {
        $value = $value ?: ($data['courseFullType'] ?? '');
        return (new CourseFullTypeEnum())->getDescription($value) ?? '';

    }

    public function getCourseDeliveryTypeCnAttr($value, $data)
    {
        $value = $value ?: ($data['courseDeliveryType'] ?? '');
        return (new CourseDeliveryTypeEnum())->getDescription($value) ?? '';

    }

    public function getActualCourseIdListAttr($value, $data)
    {
        $value = $value ?: ($data['actualCourseId'] ?? '');
        return $value ? explode(',', $value) : [];
    }

    public function getActualCourseListAttr($value, $data)
    {
        $value = $value ?: ($data['actualCourseId'] ?? '');
        return Course::where([['id', 'in', $value]])->field(['id', 'name'])->select();

    }


    //-----------------------------------------------------------------------------------
    //｜                                   处理方法                                       ｜
    //-----------------------------------------------------------------------------------

    /**
     * 根据上课记录ID获取学生机构ID
     *
     * @param int $skRecordId 上课记录ID
     * @return string 学生机构ID
     */
    public function getStudentOrgIdById($skRecordId)
    {
        return $this->where('id', $skRecordId)->value('studentOrgId');
    }

    /**
     * 更新评价
     */
    public function evaluate($accountId, $accountType, $recordId, $star, $content = '')
    {
        $info = $this->where('id', $recordId)->find();
        if (empty($info)) {
            throw new ValidateException('评价失败，上课记录不存在');
        }
        if (!$info['isEnd']) {
            throw new ValidateException('评价失败，上课记录未结束');
        }
        $studentId = $info['studentId'];
        $trainerId = $info['trainerId'];
        switch ($accountType) {
            case 'sys_user':
                $info->campusStar = $star;
                break;
            case 'student':
                if ($studentId != $accountId) {
                    throw new ValidateException('评价失败，上课记录不存在');
                }
                if ($info->studentStar) {
                    throw new ValidateException('你已经评价过了，请勿重复评价');
                }
                $info->studentStar = $star;
                $info->studentEvaluate = $content;
                break;
            case 'trainer':
                if ($trainerId != $accountId) {
                    throw new ValidateException('评价失败，上课记录不存在');
                }
                if ($info->trainerStar) {
                    throw new ValidateException('你已经评价过了，请勿重复评价');
                }
                $info->trainerStar = $star;
                $info->trainerEvaluate = $content;
                break;
        }
        $info->save();
        return true;
    }


    /**
     * 更改有效无效
     */
    public function updateValid($id)
    {
        $learnSkRecordInfo = $this->where('id', $id)->find();
        if (!$learnSkRecordInfo) {
            return true;
        }
        try {
            $updateLearnValidStatus = $learnSkRecordInfo['learnValidStatus'] == LearnValidStatusEnum::E1 ? LearnValidStatusEnum::E2 : LearnValidStatusEnum::E1;
            $learnSkRecordInfo->learnValidStatus = $updateLearnValidStatus;
            $learnSkRecordInfo->save();
            $coreTrainerMonthSalaryDetail = new TrainerSalaryProjectEnum();
            $project = $coreTrainerMonthSalaryDetail->get($learnSkRecordInfo['courseFullType']);
            $trainerSalaryService = new TrainerSalaryService();
            $res = $trainerSalaryService->updateCancel($id, $project, $updateLearnValidStatus == LearnValidStatusEnum::E2);
            if (!$res) {
                throw new ValidateException($trainerSalaryService->getError());
            }
        } catch (Exception|PDOException|ValidateException $e) {
            throw new ValidateException($e->getMessage());
        }
        return true;

    }

    /**
     * 更新课后作业(视频课)
     */
    public function updateAfterClassQuestion($id, $question)
    {
        $info = $this->where('id', $id)->find();
        if (!$info) {
            throw new ValidateException('课程不存在');
        }
        if ($info['isEnd']) {
            throw new ValidateException('课程已结束');
        }
        try {
            $questions_arr = explode(',', $question);
            $questions_list = SubjectQuestion::where([
                ['id', 'in', $questions_arr],
                ['status', '=', SubjectQuestionStatusEnum::E1]
            ])->column('id');
            if (empty($questions_list)) {
                throw new ValidateException('没有可用的题库');
            }
            $info->afterClassQuestion = $question;
            $info->save();
        } catch (Exception|PDOException|ValidateException $e) {
            throw new ValidateException($e->getMessage());
        }
        return true;

    }

    public function listByTrainer(array $trainerIds)
    {
        if (!$trainerIds) {
            return [];
        }
        return $this->whereIn('trainerId', $trainerIds)
            ->group('trainerId')
            ->field('trainerId,count(id) as count')
            ->select();
    }

    public function getListXkPage($index, $limit, $accountId, $accountType, $searchText = '')
    {
        $where = [];
        switch ($accountType) {
            case AccountTypeEnum::STUDENT:
                $where[] = ['studentId', '=', $accountId];
                break;
            case AccountTypeEnum::TRAINER:
                $where[] = ['trainerId', '=', $accountId];
                break;
            default:
                throw new ValidateException('不支持的账户类型');
        }
        if ($searchText) {
            $StudentModel = new Student();
            $studentIds = $StudentModel->where('name', 'like', '%' . $searchText . '%')->column('id');
            $studentIds = array_unique($studentIds);
            $where[] = ['studentId', 'in', $studentIds];
        }
        return $this
            ->with(['organizationBaseInfo', 'studentInfo', 'trainerInfo', 'subjectTeach', 'salaryDetail'])
            ->where($where)
            ->order('id', 'desc')
            ->paginate([
                'page' => $index,
                'list_rows' => $limit,
            ])->each(function ($item) {
                if ($item['studentOrgId'] == 0) {
                    $organizationModel = new Organization();
                    $item['organizationBaseInfo'] = $organizationModel->getOrganizationInfo();
                }
                $learnSayQuestionRecord = new LearnSayQuestionRecord();
                $data = $learnSayQuestionRecord->where('skRecordId', $item['id'])
                    ->group('skRecordId')
                    ->field('sum(learnSentenceCount) as learnSentenceCount,sum(learnWordCount) as learnWordCount')
                    ->find();
                $item['learnSentenceCount'] = $data ? $data['learnSentenceCount'] : 0;
                $item['learnWordCount'] = $data ? $data['learnWordCount'] : 0;
            });
    }

    public function getCoreVocabularySplit($list)
    {
        $wordDictionaryModel = new WordDictionary();
        $list = result_row($list);

        // 提取所有需要查询的单词
        $wordList = [];
        foreach ($list['rows'] as $item) {
            $coreVocabulary = json_decode($item['coreVocabulary'], true);
            if (is_array($coreVocabulary)) {
                foreach ($coreVocabulary as $value) {
                    if (!empty($value['wordEn'])) {
                        $wordList[] = $value['wordEn'];
                    }
                }
            }
        }

        // 批量查询单词信息
        $wordMap = [];
        if (!empty($wordList)) {
            $uniqueWords = array_unique($wordList);
            $wordInfos = $wordDictionaryModel->where('word', 'in', $uniqueWords)->select();
            foreach ($wordInfos as $wordInfo) {
                $wordMap[$wordInfo['word']] = [
                    'metaVowelList' => $wordInfo['metaVowelList'],
                    'metaConsonantList' => $wordInfo['metaConsonantList']
                ];
            }
        }

        // 处理数据并过滤无效项
        $validRows = [];
        foreach ($list['rows'] as $item) {
            $coreVocabulary = $item['coreVocabularyList'];
            $validVocabulary = [];
            if (is_array($coreVocabulary)) {
                foreach ($coreVocabulary as $value) {
                    if (!empty($value['wordEn'])) {
                        if (isset($wordMap[$value['wordEn']])) {
                            $value['metaVowelList'] = $wordMap[$value['wordEn']]['metaVowelList'];
                            $value['metaConsonantList'] = $wordMap[$value['wordEn']]['metaConsonantList'];
                        } else {
                            $value['metaVowelList'] = [];
                            $value['metaConsonantList'] = [];
                        }
                        $validVocabulary[] = $value;
                    }
                }
            }

            if (!empty($validVocabulary)) {
                $item['coreVocabularyList'] = $validVocabulary;
                $validRows[] = $item;
            }
        }

        $list['rows'] = $validRows;
        return $list;
    }


    //-----------------------------------------------------------------------------------
    //｜                                   模型关联                                       ｜
    //-----------------------------------------------------------------------------------

    public function studentInfo()
    {
        return $this->hasOne(Student::class, 'id', 'studentId');
    }

    public function trainerInfo()
    {
        return $this->hasOne(Trainer::class, 'id', 'trainerId');
    }

    public function organizationBaseInfo()
    {
        return $this->hasOne(Organization::class, 'id', 'studentOrgId');
    }

    public function accountClassHour()
    {
        return $this->hasOne(CoreAccountClassHour::class, 'studentId', 'studentId');
    }

    public function subjectTeach()
    {
        return $this->hasOne(SubjectTeach::class, 'id', 'courseId');
    }

    public function salaryDetail()
    {
        return $this->hasOne(CoreTrainerMonthSalaryDetail::class, 'recordId', 'id');
    }

    public function courseAppointment()
    {
        return $this->belongsTo(CoreCourseAppointment::class, 'appointmentId', 'id');
    }

}